package com.qinggeng.project.tool.sms.service.impl;


import com.alibaba.fastjson.JSONObject;
import com.aliyuncs.DefaultAcsClient;
import com.aliyuncs.IAcsClient;
import com.aliyuncs.dysmsapi.model.v20170525.SendSmsRequest;
import com.aliyuncs.dysmsapi.model.v20170525.SendSmsResponse;
import com.aliyuncs.profile.DefaultProfile;
import com.aliyuncs.profile.IClientProfile;
import com.qinggeng.common.constant.Constants;
import com.qinggeng.common.enums.ShowTypeEnum;
import com.qinggeng.common.enums.SmsTypeEnum;
import com.qinggeng.common.exception.CustomException;
import com.qinggeng.common.exception.UtilException;
import com.qinggeng.common.utils.DateUtils;
import com.qinggeng.common.utils.ServletUtils;
import com.qinggeng.common.utils.StringUtils;
import com.qinggeng.common.utils.ip.IpUtils;
import com.qinggeng.framework.redis.RedisCache;
import com.qinggeng.project.api.security.utils.ApiUtils;
import com.qinggeng.project.api.service.IApiMemberService;
import com.qinggeng.project.system.domain.Orders;
import com.qinggeng.project.system.domain.OrdersPoint;
import com.qinggeng.project.system.domain.SysUser;
import com.qinggeng.project.system.mapper.OrdersMapper;
import com.qinggeng.project.system.mapper.OrdersPointMapper;
import com.qinggeng.project.system.mapper.PositionMapper;
import com.qinggeng.project.system.mapper.ResumeMapper;
import com.qinggeng.project.system.service.ISysConfigService;
import com.qinggeng.project.system.service.ISysUserService;
import com.qinggeng.project.tool.sms.domain.SysSms;
import com.qinggeng.project.tool.sms.domain.json.SmsConfigJson;
import com.qinggeng.project.tool.sms.mapper.SysSmsMapper;
import com.qinggeng.project.tool.sms.service.ISysSmsService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.List;
import java.util.concurrent.TimeUnit;

/**
 * 短信通讯Service业务层处理
 *
 * @author qinggeng
 * @date 2020-03-14
 */
@Slf4j
@Service
public class SysSmsServiceImpl implements ISysSmsService
{
    @Resource
    private SysSmsMapper sysSmsMapper;

    @Autowired
    private ISysConfigService configService;

    @Autowired
    private RedisCache redisCache;
    @Autowired
    private ISysUserService sysUserService;
    @Resource
    private ResumeMapper resumeMapper;
    @Resource
    private PositionMapper positionMapper;
    @Resource
    private OrdersMapper ordersMapper;
    @Resource
    private OrdersPointMapper ordersPointMapper;
    @Autowired
    private IApiMemberService apiMemberService;


    /**
     * 查询短信通讯
     *
     * @param smsId 短信通讯ID
     * @return 短信通讯
     */
    @Override
    public SysSms selectSysSmsById(Long smsId)
    {
        return sysSmsMapper.selectSysSmsById(smsId);
    }

    /**
     * 查询短信通讯列表
     *
     * @param sysSms 短信通讯
     * @return 短信通讯
     */
    @Override
    public List<SysSms> selectSysSmsList(SysSms sysSms)
    {
        return sysSmsMapper.selectSysSmsList(sysSms);
    }

    /**
     * 新增短信通讯
     *
     * @param sysSms 短信通讯
     * @return 结果
     */
    @Override
    public int insertSysSms(SysSms sysSms)
    {
        sysSms.setCreateTime(DateUtils.getNowDate());
        return sysSmsMapper.insertSysSms(sysSms);
    }

    /**
     * 修改短信通讯
     *
     * @param sysSms 短信通讯
     * @return 结果
     */
    @Override
    public int updateSysSms(SysSms sysSms)
    {
        return sysSmsMapper.updateSysSms(sysSms);
    }

    /**
     * 批量删除短信通讯
     *
     * @param smsIds 需要删除的短信通讯ID
     * @return 结果
     */
    @Override
    public int deleteSysSmsByIds(Long[] smsIds)
    {
        return sysSmsMapper.deleteSysSmsByIds(smsIds);
    }

    /**
     * 删除短信通讯信息
     *
     * @param smsId 短信通讯ID
     * @return 结果
     */
    @Override
    public int deleteSysSmsById(Long smsId)
    {
        return sysSmsMapper.deleteSysSmsById(smsId);
    }

    @Override
    public void snedSmsRegisterCode(String phone) throws Exception {
        SmsConfigJson configObject = getConfig();
        int code = (int) ((Math.random() * 9 + 1) * 100000);
        //存放验证码发送时间 防止重复发送
        if (configObject.getSmsType().equals(SmsTypeEnum.ALIYUN.getCode())){
            //发送验证码
            sendSmsAliyun(configObject,phone,"{\"code\":\"" + code + "\"}",configObject.getRegisterCode());
        }
        //保存短位发送记录
        insertSysSms("register","验证码："+code,phone);

        //存放验证码 验证码有效期5分钟
        redisCache.setCacheObject(Constants.SMS_KEY + phone + "(register)",code+"",60 * 5, TimeUnit.SECONDS);
    }

    @Override
    public void snedSmsVerifyCode(String phone) throws Exception {
        SmsConfigJson configObject = getConfig();
        int code = (int) ((Math.random() * 9 + 1) * 100000);
        //存放验证码发送时间 防止重复发送
        //发送验证码
        if (configObject.getSmsType().equals(SmsTypeEnum.ALIYUN.getCode())) {
            sendSmsAliyun(configObject, phone, "{\"code\":\"" + code + "\"}", configObject.getVerifyCode());
        }

        //保存短位发送记录
        insertSysSms("verify","验证码："+code,phone);

        //存放验证码 验证码有效期5分钟
        redisCache.setCacheObject(Constants.SMS_KEY + phone + "(verify)",code+"",60 * 5, TimeUnit.SECONDS);
    }



    @Override
    public void sendArriveNotice(String ordersNo) throws Exception {
        Orders orders=ordersMapper.selectOrdersByOrdersNo(ordersNo);
        if(null==orders){
            return;
        }
        String phone=orders.getPickPhone();
        if(StringUtils.isEmpty(phone)){
            return;
        }
        OrdersPoint ordersPoint=ordersPointMapper.selectOrdersPointByOrdersId(orders.getOrdersId());
        if(null==ordersPoint){
            return;
        }
        //提货码
        String pickCode=ordersPoint.getSortArea()+"-"+ordersPoint.getSortAreaNum()+"-"+ordersPoint.getOrdersId();
        //获取配送点地址
        String address=ordersPoint.getAddress();
        //地址长度超过20个字符，则截取前20个字符
        if(address.length()>20){
            String[] addresses=address.split("市");
            address=addresses[addresses.length-1];
        }
        if(address.length()>20){
            address=address.substring(address.length()-20);
        }

        SmsConfigJson configObject = getConfig();
        if (configObject.getSmsType().equals(SmsTypeEnum.ALIYUN.getCode())) {
            sendSmsAliyun(configObject, phone, "{\"ordersNo\":\"" + ordersNo + "\",\"pointName\":\""+ordersPoint.getPointName()+"\",\"pickCode\":\""+pickCode+"\",\"address\":\""+address+"\",\"pointPhone\":\""+ordersPoint.getPointPhone()+"\"}",configObject.getArriveNotice());
        }

        //保存短位发送记录
        insertSysSms("arrive","提货码："+pickCode,phone);

    }

    @Override
    public void sendInitPassword(String phone, String pwd) throws Exception {
        SmsConfigJson configObject = getConfig();
        if (configObject.getSmsType().equals(SmsTypeEnum.ALIYUN.getCode())) {
            sendSmsAliyun(configObject, phone, "{\"account\":\"" + phone + "\",\"pwd\":\""+pwd+"\"}", configObject.getSendPassword());
        }
        //保存短位发送记录
        insertSysSms("initPwd","初始密码："+pwd,phone);
    }

    @Override
    public void sendResetPassword(Long userId, String pwd) throws Exception {
        SysUser sysUser=sysUserService.selectUserById(userId);
        if(null==sysUser){
            return;
        }
        String phone=sysUser.getPhonenumber();
        if(StringUtils.isEmpty(phone)){
            return ;
        }
        SmsConfigJson configObject = getConfig();
        if (configObject.getSmsType().equals(SmsTypeEnum.ALIYUN.getCode())) {
            sendSmsAliyun(configObject, phone, "{\"pwd\":\""+pwd+"\"}", configObject.getSendResetPwd());
        }
        //保存短位发送记录
        insertSysSms("resetPwd","重置密码："+pwd,phone);

    }

    @Override
    public void remove(String phone, String event) {
        redisCache.deleteObject(Constants.SMS_KEY + phone + "("+event+")");
    }

    @Override
    public SmsConfigJson getConfig() {
        try{
            String smsConfigJson = configService.selectConfigByKey("sys.sms.config").toString();
            return JSONObject.parseObject(smsConfigJson, SmsConfigJson.class);
        }catch (Exception e){
            log.error(e.getMessage());
            return new SmsConfigJson().initConfig();
        }
    }

    @Override
    public void snedSmsForgetCode(String phone) throws Exception {
        SmsConfigJson configObject = getConfig();
        int code = (int) ((Math.random() * 9 + 1) * 100000);
        //存放验证码发送时间 防止重复发送
        //发送验证码
        if (configObject.getSmsType().equals(SmsTypeEnum.ALIYUN.getCode())) {
            sendSmsAliyun(configObject, phone, "{\"code\":\"" + code + "\"}", configObject.getForgetCode());
        }
        //保存短位发送记录
        insertSysSms("forget","验证码："+code,phone);

        //存放验证码 验证码有效期5分钟
        redisCache.setCacheObject(Constants.SMS_KEY + phone + "(forget)",code+"",60 * 5, TimeUnit.SECONDS);
    }

    @Override
    public void sendSmsUpdPhoneCode(String phone) throws Exception {
        SmsConfigJson configObject = getConfig();
        int code = (int) ((Math.random() * 9 + 1) * 100000);
        //存放验证码发送时间 防止重复发送
        //发送验证码
        if (configObject.getSmsType().equals(SmsTypeEnum.ALIYUN.getCode())) {
            sendSmsAliyun(configObject, phone, "{\"code\":\"" + code + "\"}", configObject.getUpdPhoneCode());
        }
        //保存短位发送记录
        insertSysSms("updPhone","验证码："+code,phone);

        //存放验证码 验证码有效期5分钟
        redisCache.setCacheObject(Constants.SMS_KEY + phone + "(updPhone)",code+"",60 * 5, TimeUnit.SECONDS);
    }

    @Override
    public void sendSmsLoginCode(String phone) throws Exception {
        SmsConfigJson configObject = getConfig();
        int code = (int) ((Math.random() * 9 + 1) * 100000);
        //存放验证码发送时间 防止重复发送
        //发送验证码
        if (configObject.getSmsType().equals(SmsTypeEnum.ALIYUN.getCode())) {
            JSONObject jsonObject=new JSONObject();
            jsonObject.put("code",code);
            sendSmsAliyun(configObject, phone, jsonObject.toJSONString(), configObject.getLoginCode());
        }
        //保存短位发送记录
        insertSysSms("login","验证码："+code,phone);

        //存放验证码 验证码有效期5分钟
        redisCache.setCacheObject(Constants.SMS_KEY + phone + "(login)",code+"",60 * 5, TimeUnit.SECONDS);
    }


    @Override
    public String getCode(String phone, String event) {
        return (String)redisCache.getCacheObject(Constants.SMS_KEY + phone + "("+event+")");
        //return (String)redisCache.getCacheObject(Constants.SMS_KEY + phone + "(time)("+event+")");
    }


    @Override
    public void sendContact(String type, String name,String contact) {

        SysUser sysUser=sysUserService.selectUserById(ApiUtils.getUserId());
        if(null==sysUser){
            throw new CustomException("未查询到您的登录信息！");
        }
        if(StringUtils.isEmpty(sysUser.getPhonenumber())){
            throw new CustomException("请先绑定自己的手机号码！", ShowTypeEnum.用户.getValue());
        }

        SmsConfigJson configObject = getConfig();
        //发送联系方式
        if (SmsTypeEnum.ALIYUN.getCode().equals(configObject.getSmsType())) {
            try {
                sendSmsAliyun(configObject, sysUser.getPhonenumber(), "{\"type\":\""+type+"\",\"name\":\"" + name + "\",\"contact\":\""+contact+"\"}",configObject.getSendContact());
            }catch (Exception e){
                log.error(e.getMessage());
                throw new CustomException("发送联系方式失败！",ShowTypeEnum.用户.getValue());
            }
            //保存短信发送记录
            insertSysSms("sendContact","联系电话："+contact,sysUser.getPhonenumber());
        }

    }

    @Override
    public int sendSmsUsersNotice(String templateCode) {
        SmsConfigJson configObject = getConfig();
        List<SysUser> sysUserList=apiMemberService.listMember();
        int rows=0;
        for (SysUser sysUser :sysUserList
                ) {
            String phone=sysUser.getPhonenumber();
            if(StringUtils.isEmpty(phone)||phone.length()!=11){
                continue;
            }
            try {
                this.sendSmsAliyun(configObject,phone,null,templateCode);
                rows++;
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
        return rows;

    }

    /**
     * 保存短信发送记录
     * @param event
     * @param msg
     * @param phone
     */
    private int insertSysSms(String event,String msg,String phone){
        try{
            SysSms sysSms = new SysSms();
            sysSms.setEvent(event);
            sysSms.setIp(IpUtils.getIpAddr(ServletUtils.getRequest()));
            sysSms.setMsg(msg);
            sysSms.setType(SmsTypeEnum.ALIYUN.getCode());
            sysSms.setPhone(phone);
            return sysSmsMapper.insertSysSms(sysSms);
        }catch (Exception e){
            e.printStackTrace();
        }
        return 0;
    }

public void sendSmsAliyunActivity(SmsConfigJson configObject, String phone,String templateParam, String templateCode){
     try{
         this.sendSmsAliyun(configObject,phone,templateParam,templateCode);
     }catch (Exception e){
        e.printStackTrace();
     }
}

    private void sendSmsAliyun(SmsConfigJson configObject, String phone, String templateParam, String templateCode) throws Exception{

        System.setProperty("sun.net.client.defaultConnectTimeout", "10000");

        System.setProperty("sun.net.client.defaultReadTimeout", "10000");
        // 初始化acsClient,暂不支持region化

        IClientProfile profile = DefaultProfile.getProfile("cn-hangzhou", configObject.getAccessKeyId(), configObject.getAccessKeySecret());
        DefaultProfile.addEndpoint("cn-hangzhou", "cn-hangzhou", "Dysmsapi", "dysmsapi.aliyuncs.com");
        IAcsClient acsClient = new DefaultAcsClient(profile);

        // 组装请求对象-具体描述见控制台-文档部分内容
        SendSmsRequest request = new SendSmsRequest();
        // 必填:待发送手机号

        request.setPhoneNumbers(phone);
        // 必填:短信签名-可在短信控制台中找到
        request.setSignName(configObject.getSignName());
        // 必填:短信模板-可在短信控制台中找到
        request.setTemplateCode(templateCode);
        // 可选:模板中的变量替换JSON串,如模板内容为"亲爱的${name},您的验证码为${code}"时,此处的值为
        request.setTemplateParam(templateParam);
        // 选填-上行短信扩展码(无特殊需求用户请忽略此字段)
        // request.setSmsUpExtendCode("90997");
        // 可选:outId为提供给业务方扩展字段,最终在短信回执消息中将此值带回给调用者
//        request.setOutId("yourOutId");
        // hint 此处可能会抛出异常，注意catch
        SendSmsResponse sendSmsResponse = acsClient.getAcsResponse(request);
        if (!sendSmsResponse.getCode().equals("OK")){
            throw new UtilException("发送短信异常："+sendSmsResponse.getMessage());
        }
    }
}
